home *** CD-ROM | disk | FTP | other *** search
/ Apple WWDC 1996 / WWDC96_1996 (CD).toast / Technology Materials / MacApp Release 10 / MacApp Release 10 - HD Ready / Libraries / Core / Sources / UStream.cp < prev    next >
Encoding:
Text File  |  1996-04-03  |  40.7 KB  |  1,481 lines  |  [TEXT/MPS ]

  1. //----------------------------------------------------------------------------------------
  2. // UStream.cp 
  3. // Copyright © 1990-96 by Apple Computer, Inc. All rights reserved.
  4. //
  5. // Originally written by Larry S. Rosenstein.  Used by permission 
  6. //----------------------------------------------------------------------------------------
  7.  
  8. #ifndef __USTREAM__
  9. #include "UStream.h"
  10. #endif
  11.  
  12. // MacApp
  13.  
  14. #ifndef __GEOMETRY__
  15. #include "Geometry.h"
  16. #endif
  17.  
  18. #ifndef __UFAILURE__
  19. #include "UFailure.h"
  20. #endif
  21.  
  22. #ifndef __ULIST__
  23. #include "UList.h"
  24. #endif
  25.  
  26. #ifndef __ULISTITERATOR__
  27. #include "UListIterator.h"
  28. #endif
  29.  
  30. #ifndef __UCOREGLOBALS__
  31. #include "UCoreGlobals.h"
  32. #endif
  33.  
  34. #ifndef __UCOREUTILITIES__
  35. #include "UCoreUtilities.h"
  36. #endif
  37.  
  38. #ifndef __UMEMORY__
  39. #include "UMemory.h"
  40. #endif
  41.  
  42. #ifndef __UPATCH__
  43. #include "UPatch.h"
  44. #endif
  45.  
  46. // Toolbox
  47.  
  48. #ifndef __ERRORS__
  49. #include <Errors.h>
  50. #endif
  51.  
  52. #ifndef __FILES__
  53. #include <Files.h>
  54. #endif
  55.  
  56. #ifndef __LOWMEM__
  57. #include <LowMem.h>
  58. #endif
  59.  
  60. #ifndef __OSUTILS__
  61. #include <OSUtils.h>
  62. #endif
  63.  
  64. #ifndef __RESOURCES__
  65. #include <Resources.h>
  66. #endif
  67.  
  68. #ifndef __TEXTEDIT__
  69. #include <TextEdit.h>
  70. #endif
  71.  
  72. // ANSI
  73.  
  74. #ifndef __LIMITS__
  75. #include <limits.h>
  76. #endif
  77.  
  78.  
  79. //========================================================================================
  80. // CLASS TContext
  81. //========================================================================================
  82. #undef Inherited
  83. #define Inherited TObject
  84.  
  85. #pragma segment MAStreamCreate
  86. MA_DEFINE_CLASS_M1(TContext,
  87.                    Inherited);
  88.  
  89. //----------------------------------------------------------------------------------------
  90. // TContext constructor
  91. //----------------------------------------------------------------------------------------
  92. #pragma segment MAStreamCreate
  93.  
  94. TContext::TContext() :
  95.     fOtherObjects(NULL)
  96. {
  97. }
  98.  
  99. //----------------------------------------------------------------------------------------
  100. // TContext::IContext: 
  101. //----------------------------------------------------------------------------------------
  102. #pragma segment MAStreamCreate
  103.  
  104. void TContext::IContext()
  105. {
  106.     IObject();
  107.  
  108.     FailInfo fi;
  109.     Try(fi)
  110.     {
  111.         fOtherObjects = NewList();
  112.         fi.Success();
  113.     }
  114.     else
  115.     {
  116.         Free();
  117.         fi.ReSignal();
  118.     }
  119. }
  120.  
  121. //----------------------------------------------------------------------------------------
  122. // TContext::Free: 
  123. //----------------------------------------------------------------------------------------
  124. #pragma segment MAStreamFree
  125.  
  126. TContext::~TContext()
  127. {
  128.     fOtherObjects = (TList *)FreeIfObject((TObject *)fOtherObjects);// don't call FreeList
  129. }
  130.  
  131. //----------------------------------------------------------------------------------------
  132. // TContext::Clone: 
  133. //----------------------------------------------------------------------------------------
  134. #pragma segment MAStreamUtil
  135.  
  136. TObject* TContext::Clone()
  137.  
  138. {
  139.     MAVolatileInit(TContext * , aClonedContext, (TContext *)Inherited::Clone());
  140.     aClonedContext->fOtherObjects = NULL;        // so failure handler works
  141.  
  142.     FailInfo fi;
  143.     Try(fi)                                        // In case allocation fails, object is freed.
  144.     {
  145.         aClonedContext->fOtherObjects = (TList *)fOtherObjects->Clone();
  146.         fi.Success();
  147.     }
  148.     else                                        // Recover
  149.     {
  150.         aClonedContext->Free();                // Free the stream if it can't be initialized
  151.         fi.ReSignal();
  152.     }
  153.  
  154.     return aClonedContext;
  155. }
  156.  
  157. //----------------------------------------------------------------------------------------
  158. // TContext::Add: 
  159. //----------------------------------------------------------------------------------------
  160. #pragma segment MAStreamUtil
  161.  
  162. LocalObjectNumber TContext::Add(TObject* objectToAdd,
  163.                                 Boolean forceReplacement,
  164.                                 Boolean& newEntry)
  165. {
  166.     LocalObjectNumber retval = 0;
  167.  
  168.     // Look for object
  169.     CObjectIterator iter(fOtherObjects);
  170.  
  171.     for (TObject * obj = iter.FirstObject(); iter.More(); obj = iter.NextObject())
  172.     {
  173.         if (objectToAdd == obj)
  174.         {
  175.             retval = iter.CurrentIndex();
  176.             break;
  177.         }
  178.     }
  179.  
  180.     if (retval == 0)
  181.     {
  182.         fOtherObjects->InsertLast(objectToAdd);
  183.         retval = fOtherObjects->GetSize();
  184.         newEntry = TRUE;
  185.     }
  186.     else if (forceReplacement)                    // We force replacement
  187.     {
  188.         fOtherObjects->AtPut(retval, objectToAdd);
  189.         newEntry = TRUE;
  190.     }
  191.     else
  192.         newEntry = FALSE;
  193.  
  194.     return retval;
  195. }
  196.  
  197. //----------------------------------------------------------------------------------------
  198. // TContext::Find: 
  199. //----------------------------------------------------------------------------------------
  200. #pragma segment MAStreamUtil
  201.  
  202. TObject* TContext::Find(LocalObjectNumber name)
  203. {
  204.     return fOtherObjects->At(name);
  205. }
  206.  
  207.  
  208. //========================================================================================
  209. // CLASS TStream
  210. //========================================================================================
  211. #undef Inherited
  212. #define Inherited TObject
  213.  
  214. #pragma segment MAStreamCreate
  215. MA_DEFINE_CLASS_M1(TStream,
  216.                    Inherited);
  217.  
  218. //----------------------------------------------------------------------------------------
  219. // TStream constructor
  220. //----------------------------------------------------------------------------------------
  221. #pragma segment MAStreamCreate
  222.  
  223. TStream::TStream() :
  224.     fClassMap(NULL),
  225.     fClassMapSize(0),
  226.     fContext(NULL)
  227. {
  228. }
  229.  
  230. //----------------------------------------------------------------------------------------
  231. // TStream::IStream: 
  232. //----------------------------------------------------------------------------------------
  233. #pragma segment MAStreamCreate
  234.  
  235. void TStream::IStream()
  236. {
  237.     IObject();
  238.  
  239.     FailInfo fi;
  240.     Try(fi)                                        // In case allocation fails, object is freed.
  241.     {
  242.         fClassMap = (HClassArray)NewPermHandle(0);
  243.         fi.Success();
  244.     }
  245.     else                                        // Recover
  246.     {
  247.         Free();                                // Free the stream if it can't be initialized
  248.         fi.ReSignal();
  249.     }
  250. }
  251.  
  252. //----------------------------------------------------------------------------------------
  253. // TStream::AtEnd: 
  254. //----------------------------------------------------------------------------------------
  255. #pragma segment MAStreamUtil
  256.  
  257. Boolean TStream::AtEnd()
  258. {
  259.     return (GetPosition() >= GetSize()) ? TRUE : FALSE;
  260. }
  261.  
  262. //----------------------------------------------------------------------------------------
  263. // TStream::Free: 
  264. //----------------------------------------------------------------------------------------
  265. #pragma segment MAStreamFree
  266.  
  267. TStream::~TStream()
  268. {
  269.     fContext = (TContext *)FreeIfObject((TObject *)fContext);
  270.     fClassMap = (HClassArray)DisposeIfHandle((Handle)fClassMap);
  271. }
  272.  
  273. //----------------------------------------------------------------------------------------
  274. // TStream::GetPosition: 
  275. //----------------------------------------------------------------------------------------
  276. #pragma segment MAStreamUtil
  277.  
  278. long TStream::GetPosition()
  279. {
  280.     return 0;
  281. }
  282.  
  283. //----------------------------------------------------------------------------------------
  284. // TStream::GetSize: 
  285. //----------------------------------------------------------------------------------------
  286. #pragma segment MAStreamUtil
  287.  
  288. long TStream::GetSize()
  289. {
  290.     return 0;
  291. }
  292.  
  293.  
  294. //----------------------------------------------------------------------------------------
  295. // TStream::LookupClassID: This returns the new class ID given a class ID found in the
  296. // stream, or kNilClass if it wasn't found. It does a simple linear search.
  297. //----------------------------------------------------------------------------------------
  298. #pragma segment MAStreamUtil
  299.  
  300. long TStream::LookupClassID(long id)
  301. {
  302.     if (id != kNilClass)
  303.         for (short i = 0; i < fClassMapSize; ++i)
  304.             if ((*fClassMap)[i].fOldID == id)
  305.                 return (*fClassMap)[i].fNewID;
  306.     return kNilClass;
  307. }
  308.  
  309. //----------------------------------------------------------------------------------------
  310. // TStream::ReadBytes: 
  311. //----------------------------------------------------------------------------------------
  312. #pragma segment MAStreamNever
  313.  
  314. void TStream::ReadBytes(void* ,
  315.                         long)
  316. {
  317.     SubClassResponsibility();
  318. }
  319.  
  320. //----------------------------------------------------------------------------------------
  321. // TStream::ReadByte: 
  322. //----------------------------------------------------------------------------------------
  323. #pragma segment MAStreamRead
  324.  
  325. Byte TStream::ReadByte()
  326. {
  327.     Byte data;
  328.  
  329.     ReadBytes(&data, sizeof(Byte));
  330.  
  331.     return data;
  332. }
  333.  
  334. //----------------------------------------------------------------------------------------
  335. // TStream::ReadBoolean: 
  336. //----------------------------------------------------------------------------------------
  337. #pragma segment MAStreamRead
  338.  
  339. Boolean TStream::ReadBoolean()
  340. {
  341.     Boolean data;
  342.  
  343.     ReadBytes(&data, sizeof(Boolean));
  344.  
  345.     return data;
  346. }
  347.  
  348. //----------------------------------------------------------------------------------------
  349. // TStream::ReadCharacter: The trick here is that characters are represented as 2 bytes,
  350. // with the actual data in the low order byte.
  351. //----------------------------------------------------------------------------------------
  352. #pragma segment MAStreamRead
  353.  
  354. void TStream::ReadCharacter(short& data)
  355. {
  356.     data = 0;                                    // Clear the high order byte.
  357.     ReadBytes((char*) & data + 1, 1);
  358. }
  359.  
  360. //----------------------------------------------------------------------------------------
  361. // TStream::ReadInteger: 
  362. //----------------------------------------------------------------------------------------
  363. #pragma segment MAStreamRead
  364.  
  365. short TStream::ReadInteger()
  366. {
  367.     short data;
  368.  
  369.     ReadBytes(&data, sizeof(short));
  370.  
  371.     return data;
  372. }
  373.  
  374. //----------------------------------------------------------------------------------------
  375. // TStream::ReadLong: 
  376. //----------------------------------------------------------------------------------------
  377. #pragma segment MAStreamRead
  378.  
  379. long TStream::ReadLong()
  380. {
  381.     long data;
  382.  
  383.     ReadBytes(&data, sizeof(long));
  384.  
  385.     return data;
  386. }
  387.  
  388. //----------------------------------------------------------------------------------------
  389. // TStream::ReadString: 
  390. //----------------------------------------------------------------------------------------
  391. #pragma segment MAStreamRead
  392.  
  393. void TStream::ReadString(CString& data,
  394.                          short maxSize)
  395. {
  396.     ReadBytes(&data, 1);                        // Read the length byte. 
  397.  
  398.     if (data.Length() + 1 > maxSize)
  399.         FailOSErr(paramErr);                    // Can't read that many bytes. 
  400.     else
  401.         ReadBytes(&data[1], (long)data.Length());
  402. }
  403.  
  404. //----------------------------------------------------------------------------------------
  405. // TStream::ReadHandle: 
  406. //----------------------------------------------------------------------------------------
  407. #pragma segment MAStreamRead
  408.  
  409. Handle TStream::ReadHandle()
  410. {
  411.     Handle aHandle = NULL;
  412.  
  413.     // read the size of the handle in from the stream
  414.     Size itsSize = ReadLong();
  415.  
  416.     if (itsSize >= 0)
  417.     {
  418.         // allocate the handle
  419.         aHandle = NewPermHandle(itsSize);
  420.  
  421.         // read the handle in from the stream
  422.         FailInfo fi;
  423.         Try(fi)
  424.         {
  425.             // Lock the handle and read into it from the stream. 
  426.             // We definitely need to lock the handle here because
  427.             // the code in ReadBytes may move memory before reading
  428.             // the data. 
  429.             SignedByte savedState = LockHandle(aHandle);
  430.             FailMemError();
  431.             ReadBytes(*aHandle, itsSize);
  432.             HSetState(aHandle, savedState);
  433.  
  434.             fi.Success();
  435.         }
  436.         else                                    // Recover
  437.         {
  438.             aHandle = DisposeIfHandle(aHandle);
  439.             fi.ReSignal();
  440.         }
  441.     }
  442.  
  443.     return aHandle;
  444. }
  445.  
  446. //----------------------------------------------------------------------------------------
  447. // TStream::ReadStdObject: 
  448. //----------------------------------------------------------------------------------------
  449. #pragma segment MAStreamRead
  450.  
  451. Boolean TStream::ReadStdObject(TObject*& data)
  452. {
  453.     IDType itsSignature;
  454.     long sizePosition;
  455.     long objectSize;
  456.     ClassName className;
  457.     Boolean known;
  458.  
  459.     itsSignature = ReadIDType();                // Read the object's signature. 
  460.  
  461.     sizePosition = GetPosition();                // Read its size and remember the current position.
  462.     objectSize = ReadLong();
  463.  
  464.     ReadString(className, sizeof(MAName));        // Read its name. 
  465.  
  466.     data = NULL;
  467.  
  468.     if (className.IsEmpty())
  469.         data = (TObject *)ClassDesc::NewBySignature(itsSignature);
  470.     else
  471.         data = (TObject *)ClassDesc::NewByClassName(className);
  472.  
  473.     if (data)
  474.         known = TRUE;
  475.     else                                        // Don't know about the class. 
  476.         {
  477.             // If the streamID is kNilClass then the object was realy
  478.             //    NULL, which is a known object, otherwise the class
  479.             //    isn't available.
  480.             known = FALSE;
  481.  
  482.             // Skip over the object's data. 
  483.             SetPosition(sizePosition + objectSize);// Skip over its data. 
  484.         }
  485.  
  486.     return known;
  487. }
  488.  
  489. //----------------------------------------------------------------------------------------
  490. // TStream::ReadObject: 
  491. //----------------------------------------------------------------------------------------
  492. #pragma segment MAStreamRead
  493.  
  494. Boolean TStream::ReadObject(TObject*& data)
  495. {
  496.     long streamID;                                // Class ID in stream. 
  497.     long currentID;                                // Class ID in program. 
  498.     long sizePosition;
  499.     long objectSize;
  500.     ClassName className;
  501.     Boolean known;
  502.  
  503.     ReadBytes(&streamID, sizeof(long));            // Read the object's class ID. 
  504.  
  505.     sizePosition = GetPosition();                // Read its size and remember the current position.
  506.     objectSize = ReadLong();
  507.  
  508.     ReadString(className, sizeof(MAName));        // Read its name. 
  509.  
  510.     if (className.IsEmpty())                    // No class name. Must have seen the class
  511.     // before, so convert the streamID to the
  512.     // currentID.
  513.         currentID = LookupClassID(streamID);
  514.     else
  515.     {                                            // Get ID from name ...
  516.         currentID = ClassDesc::GetClassDescFromClassName(className)->GetClassID();
  517.         RegisterClassID(streamID, currentID);    // ... and register the IDs. 
  518.     }
  519.  
  520.     data = NULL;
  521.  
  522.     if (currentID == kNilClass)                    // Don't know about the class. 
  523.     {
  524.         // If the streamID is kNilClass then the object was realy
  525.         //    NULL, which is a known object, otherwise the class
  526.         //    isn't available.
  527.         known = streamID == kNilClass;
  528.  
  529.         // Skip over the object's data. 
  530.         SetPosition(sizePosition + objectSize);    // Skip over its data. 
  531.     }
  532.     else
  533.     {                                            // Create the object. 
  534.         data = (TObject *)ClassDesc::NewByClassID((ClassID)currentID);
  535.         known = TRUE;
  536.     }
  537.  
  538.     return known;
  539. }
  540.  
  541. //----------------------------------------------------------------------------------------
  542. // TStream::ReadPoint: 
  543. //----------------------------------------------------------------------------------------
  544. #pragma segment MAStreamRead
  545.  
  546. CPoint TStream::ReadPoint()
  547. {
  548.     CPoint data;
  549.  
  550.     ReadBytes(&data, sizeof(CPoint));
  551.  
  552.     return data;
  553. }
  554.  
  555. //----------------------------------------------------------------------------------------
  556. // TStream::ReadVPoint: 
  557. //----------------------------------------------------------------------------------------
  558. #pragma segment MAStreamRead
  559.  
  560. void TStream::ReadVPoint(VPoint& data)
  561. {
  562.     ReadBytes(&data, sizeof(VPoint));
  563. }
  564.  
  565. //----------------------------------------------------------------------------------------
  566. // TStream::ReadRect: 
  567. //----------------------------------------------------------------------------------------
  568. #pragma segment MAStreamRead
  569.  
  570. void TStream::ReadRect(CRect& data)
  571. {
  572.     ReadBytes(&data, sizeof(CRect));
  573. }
  574.  
  575. //----------------------------------------------------------------------------------------
  576. // TStream::ReadVRect: 
  577. //----------------------------------------------------------------------------------------
  578. #pragma segment MAStreamRead
  579.  
  580. void TStream::ReadVRect(VRect& data)
  581. {
  582.     ReadBytes(&data, sizeof(VRect));
  583. }
  584.  
  585. //----------------------------------------------------------------------------------------
  586. // TStream::ReadRGBColor: 
  587. //----------------------------------------------------------------------------------------
  588. #pragma segment MAStreamRead
  589.  
  590. void TStream::ReadRGBColor(CRGBColor& data)
  591. {
  592.     ReadBytes(&data, sizeof(CRGBColor));
  593. }
  594.  
  595. //----------------------------------------------------------------------------------------
  596. // TStream::ReadIDType: 
  597. //----------------------------------------------------------------------------------------
  598. #pragma segment MAStreamRead
  599.  
  600. IDType TStream::ReadIDType()
  601. {
  602.     IDType data;
  603.  
  604.     ReadBytes(&data, sizeof(IDType));
  605.  
  606.     return data;
  607. }
  608.  
  609. //----------------------------------------------------------------------------------------
  610. // TStream::ReadStreamObject: 
  611. //----------------------------------------------------------------------------------------
  612. #pragma segment MAStreamRead
  613.  
  614. Boolean TStream::ReadStreamObject(TObject*& data)
  615. {
  616.     Boolean known = FALSE;
  617.     short delimiter;
  618.     LocalObjectNumber itsObjectNumber;
  619.     TContext * itsContext = GetContext();
  620.  
  621.     delimiter = ReadInteger();
  622.  
  623.     if (delimiter == kNullObject)
  624.     {
  625.         data = NULL;
  626.         known = TRUE;
  627.     }
  628.     else if (delimiter == kLocalObjectNumber)
  629.     {
  630.         ReadBytes(&itsObjectNumber, sizeof(LocalObjectNumber));
  631.         if (itsContext)
  632.             data = itsContext->Find(itsObjectNumber);
  633. #if qDebugMsg
  634.         else
  635.             ProgramBreak("###Need a TContext in TStream::ReadStreamObject.");
  636. #endif
  637.  
  638.         if (data)
  639.             known = TRUE;
  640.     }
  641.     else
  642.     {
  643.         if (delimiter == kClassIDAndClassname)
  644.             known = ReadObject(data);            // Create an uninitialized object. 
  645.         else if (delimiter == kSignatureAndClassname)
  646.             known = ReadStdObject(data);        // Create an uninitialized object by signature. 
  647. #if qDebugMsg
  648.         else
  649.             ProgramBreak("###Unknown delimiter in TStream::ReadStreamObject.");
  650. #endif
  651.  
  652.         if (known)
  653.         {
  654.             Boolean newEntry = FALSE;
  655.             if (itsContext)
  656.                 itsObjectNumber = itsContext->Add(data, kDontForceReplacement, newEntry);
  657.  
  658.             FailInfo fi;
  659.             Try(fi)
  660.             {
  661.                 if (data)                        // If we got an object, then tell it to initialize itself.
  662.                     data->ReadFrom(this);
  663.                 fi.Success();
  664.             }
  665.             else
  666.             {
  667.                 data = NULL;                    // Data should have been freed by ReadFields
  668.                 // so just make sure that we return a null
  669.                 // null reference.
  670.                 fi.ReSignal();
  671.             }
  672.         }
  673.     }
  674.     return known;
  675. }
  676.  
  677. //----------------------------------------------------------------------------------------
  678. // TStream::ReadWordAlign: 
  679. //----------------------------------------------------------------------------------------
  680. #pragma segment MAStreamRead
  681.  
  682. void TStream::ReadWordAlign()
  683. {
  684.     if (odd(GetPosition()))
  685.     {
  686.         Byte junk;
  687.         ReadBytes(&junk, sizeof(Byte));
  688.     }
  689. }
  690.  
  691. //----------------------------------------------------------------------------------------
  692. // TStream::RegisterClassID: This simply adds the mapping to the end of the list. It does
  693. // not check to see if the mapping exists already.
  694. //----------------------------------------------------------------------------------------
  695. #pragma segment MAStreamUtil
  696.  
  697. void TStream::RegisterClassID(long oldID,
  698.                               long newID)
  699. {
  700.     if (oldID != kNilClass)
  701.     {
  702.         ++fClassMapSize;
  703.         SetPermHandleSize((Handle)fClassMap, fClassMapSize * sizeof(ClassIDEntry));
  704.  
  705.         (*fClassMap)[fClassMapSize - 1].fOldID = oldID;
  706.         (*fClassMap)[fClassMapSize - 1].fNewID = newID;
  707.     }
  708. }
  709.  
  710. //----------------------------------------------------------------------------------------
  711. // TStream::SetPosition: 
  712. //----------------------------------------------------------------------------------------
  713. #pragma segment MAStreamUtil
  714.  
  715. void TStream::SetPosition(long                    /* newPosition */)
  716. {
  717. }
  718.  
  719. //----------------------------------------------------------------------------------------
  720. // TStream::SetSize: 
  721. //----------------------------------------------------------------------------------------
  722. #pragma segment MAStreamUtil
  723.  
  724. void TStream::SetSize(long                        /* newSize */)
  725. {
  726. }
  727.  
  728. //----------------------------------------------------------------------------------------
  729. // TStream::WriteBytes: 
  730. //----------------------------------------------------------------------------------------
  731. #pragma segment MAStreamNever
  732.  
  733. void TStream::WriteBytes(const void* ,
  734.                          long)
  735. {
  736.     SubClassResponsibility();
  737. }
  738.  
  739. //----------------------------------------------------------------------------------------
  740. // TStream::WriteByte: 
  741. //----------------------------------------------------------------------------------------
  742. #pragma segment MAStreamWrite
  743.  
  744. void TStream::WriteByte(Byte data)
  745. {
  746.     WriteBytes(&data, sizeof(Byte));
  747. }
  748.  
  749. //----------------------------------------------------------------------------------------
  750. // TStream::WriteBoolean: 
  751. //----------------------------------------------------------------------------------------
  752. #pragma segment MAStreamWrite
  753.  
  754. void TStream::WriteBoolean(Boolean data)
  755. {
  756.     WriteBytes(&data, sizeof(Boolean));
  757. }
  758.  
  759. //----------------------------------------------------------------------------------------
  760. // TStream::WriteCharacter: 
  761. //----------------------------------------------------------------------------------------
  762. #pragma segment MAStreamWrite
  763.  
  764. void TStream::WriteCharacter(short data)
  765. {
  766.     WriteBytes((char*) & data + 1, 1);            // Again, the data is in the low order byte.
  767. }
  768.  
  769. //----------------------------------------------------------------------------------------
  770. // TStream::WriteInteger: 
  771. //----------------------------------------------------------------------------------------
  772. #pragma segment MAStreamWrite
  773.  
  774. void TStream::WriteInteger(short data)
  775.  
  776. {
  777.     WriteBytes(&data, sizeof(short));
  778. }
  779.  
  780. //----------------------------------------------------------------------------------------
  781. // TStream::WriteLong: 
  782. //----------------------------------------------------------------------------------------
  783. #pragma segment MAStreamWrite
  784.  
  785. void TStream::WriteLong(long data)
  786.  
  787. {
  788.     WriteBytes(&data, sizeof(long));
  789. }
  790.  
  791. //----------------------------------------------------------------------------------------
  792. // TStream::WriteStreamObject: 
  793. //----------------------------------------------------------------------------------------
  794. #pragma segment MAStreamWrite
  795.  
  796. void TStream::WriteStreamObject(TObject* data,
  797.                                 Boolean stdObject)
  798. {
  799.     long sizePosition;
  800.     short delimiter = kClassIDAndClassname;
  801.     LocalObjectNumber itsObjectNumber;
  802.     Boolean newEntry = FALSE;
  803.  
  804.     if (!data)
  805.         delimiter = kNullObject;
  806.     else
  807.     {
  808.         if (stdObject)
  809.             delimiter = kSignatureAndClassname;
  810.  
  811.         TContext * itsContext = GetContext();
  812.         if (itsContext)
  813.         {
  814.             itsObjectNumber = itsContext->Add(data, kDontForceReplacement, newEntry);
  815.             if (!newEntry)
  816.                 delimiter = kLocalObjectNumber;
  817.         }
  818.     }
  819.  
  820.     WriteInteger(delimiter);
  821.  
  822.     if (delimiter == kNullObject)
  823.         ;                                        // write nothing
  824.     else if (delimiter == kLocalObjectNumber)
  825.         WriteBytes(&itsObjectNumber, sizeof(LocalObjectNumber));
  826.     else
  827.     {
  828.         if (delimiter == kClassIDAndClassname)
  829.             WriteObject(data, sizePosition);    // Write the object header. 
  830.         else
  831.             WriteStdObject(data, sizePosition);    // Write the object header. 
  832.  
  833.         if (data)                                // Write the private data. 
  834.             data->WriteTo(this);
  835.  
  836.         WriteObjectSize(sizePosition);            // Write the object size. 
  837.     }
  838. }
  839.  
  840. //----------------------------------------------------------------------------------------
  841. // TStream::WriteStdObject: 
  842. //----------------------------------------------------------------------------------------
  843. #pragma segment MAStreamWrite
  844.  
  845. void TStream::WriteStdObject(TObject* data,
  846.                              long& sizePosition)
  847. {
  848.     IDType itsSignature = data ? data->GetStandardSignature() : kNoIdentifier;
  849.  
  850.     WriteIDType(itsSignature);                    // Write the signature. 
  851.  
  852.     sizePosition = GetPosition();                // Return the position of the object size
  853.  
  854.     WriteLong(LONG_MAX);                        // Write a dummy size (maximum object size).
  855.  
  856.     ClassName className;
  857.     if (data)                                    // data is not NULL
  858.     {
  859.         data->GetClassName(className);            // Get the actual class name. 
  860.         if (itsSignature != kNoIdentifier)
  861.         {
  862.             const ClassDesc* signatureClassDesc = ClassDesc::GetClassDescFromSignature(itsSignature);
  863.             if (signatureClassDesc != NULL && signatureClassDesc == data->GetClassDescDynamic())
  864.                 className.Empty();                // then no need for class name in stream
  865.         }
  866.     }
  867.  
  868.     WriteString(className);                        // Write the class name (which may be empty).
  869. }
  870.  
  871. //----------------------------------------------------------------------------------------
  872. // TStream::WriteObject: 
  873. //----------------------------------------------------------------------------------------
  874. #pragma segment MAStreamWrite
  875.  
  876. void TStream::WriteObject(TObject* data,
  877.                           long& sizePosition)
  878. {
  879.     long streamID = data ? data->GetClassID() : kNilClass;
  880.  
  881.     WriteBytes(&streamID, sizeof(long));        // Write the class ID. 
  882.  
  883.     sizePosition = GetPosition();                // Remember the position of the object size
  884.     // in the stream.
  885.  
  886.     WriteLong(LONG_MAX);                        // Write a dummy size (maximum object size).
  887.  
  888.     ClassName className;
  889.     if ((data) && (LookupClassID(streamID) == kNilClass))
  890.     // data is not NULL, and this is the first object of the class. 
  891.     {
  892.         data->GetClassName(className);            // Get the actual class name. 
  893.  
  894.         // Register the ID, so we don't write the class name the next time
  895.         //    we write an object of this class.  The second parameter
  896.         //    doesn't matter,  as long as it isn't kNilClass.
  897.         RegisterClassID(streamID, streamID);
  898.     }
  899.  
  900.     WriteString(className);                        // Write the class name (which may be empty).
  901. }
  902.  
  903. //----------------------------------------------------------------------------------------
  904. // TStream::WriteObjectSize: 
  905. //----------------------------------------------------------------------------------------
  906. #pragma segment MAStreamWrite
  907.  
  908. // This fills in the object's size at the position passed in. 
  909. void TStream::WriteObjectSize(long sizePosition)
  910. {
  911.     long currentPosition = GetPosition();        // Remember where we are. 
  912.     SetPosition(sizePosition);                    // Go back to position of size. 
  913.  
  914.     WriteLong(currentPosition - sizePosition);    // Write the size. 
  915.  
  916.     SetPosition(currentPosition);                // Go back to where we were. 
  917. }
  918.  
  919. //----------------------------------------------------------------------------------------
  920. // TStream::WritePoint: 
  921. //----------------------------------------------------------------------------------------
  922. #pragma segment MAStreamWrite
  923.  
  924. void TStream::WritePoint(CPoint data)
  925. {
  926.     WriteBytes(&data, sizeof(CPoint));
  927. }
  928.  
  929. //----------------------------------------------------------------------------------------
  930. // TStream::WriteVPoint: 
  931. //----------------------------------------------------------------------------------------
  932. #pragma segment MAStreamWrite
  933.  
  934. void TStream::WriteVPoint(const VPoint& data)
  935. {
  936.     WriteBytes(&data, sizeof(VPoint));
  937. }
  938.  
  939. //----------------------------------------------------------------------------------------
  940. // TStream::WriteRect: 
  941. //----------------------------------------------------------------------------------------
  942. #pragma segment MAStreamWrite
  943.  
  944. void TStream::WriteRect(const CRect& data)
  945. {
  946.     WriteBytes(&data, sizeof(CRect));
  947. }
  948.  
  949. //----------------------------------------------------------------------------------------
  950. // TStream::WriteVRect: 
  951. //----------------------------------------------------------------------------------------
  952. #pragma segment MAStreamWrite
  953.  
  954. void TStream::WriteVRect(const VRect& data)
  955. {
  956.     WriteBytes(&data, sizeof(VRect));
  957. }
  958.  
  959. //----------------------------------------------------------------------------------------
  960. // TStream::WriteRGBColor: 
  961. //----------------------------------------------------------------------------------------
  962. #pragma segment MAStreamWrite
  963.  
  964. void TStream::WriteRGBColor(const CRGBColor& data)
  965. {
  966.     WriteBytes(&data, sizeof(CRGBColor));
  967. }
  968.  
  969. //----------------------------------------------------------------------------------------
  970. // TStream::WriteIDType: 
  971. //----------------------------------------------------------------------------------------
  972. #pragma segment MAStreamWrite
  973.  
  974. void TStream::WriteIDType(const IDType data)
  975.  
  976. {
  977.     WriteBytes(&data, sizeof(IDType));
  978. }
  979.  
  980. //----------------------------------------------------------------------------------------
  981. // TStream::WriteWordAlign: 
  982. //----------------------------------------------------------------------------------------
  983. #pragma segment MAStreamWrite
  984.  
  985. void TStream::WriteWordAlign()
  986. {
  987.     if (odd(GetPosition()))
  988.     {
  989.         Byte junk = 0;
  990.         WriteBytes(&junk, sizeof(Byte));
  991.     }
  992. }
  993.  
  994. //----------------------------------------------------------------------------------------
  995. // TStream::WriteString: 
  996. //----------------------------------------------------------------------------------------
  997. #pragma segment MAStreamWrite
  998.  
  999. void TStream::WriteString(const CString& data)
  1000. {
  1001.     WriteBytes(&data, ((long)data.Length()) + 1);// + 1 to include length byte. 
  1002. }
  1003.  
  1004. //----------------------------------------------------------------------------------------
  1005. // TStream::WriteHandle: 
  1006. //----------------------------------------------------------------------------------------
  1007. #pragma segment MAStreamWrite
  1008.  
  1009. void TStream::WriteHandle(const Handle aHandle)
  1010. {
  1011.     if (aHandle == NULL)
  1012.         WriteLong(-1);
  1013.     else
  1014.     {
  1015.         // write the size of the handle
  1016.         Size itsSize = GetHandleSize(aHandle);
  1017.         WriteLong(itsSize);
  1018.  
  1019.         // Write the contents of the handle. 
  1020.         // We definitely need to lock the handle here because
  1021.         // the code in WriteBytes may move memory before reading
  1022.         // the data. 
  1023.         SignedByte savedState = LockHandle(aHandle);
  1024.         FailMemError();
  1025.         WriteBytes(*aHandle, itsSize);
  1026.         HSetState(aHandle, savedState);
  1027.     }
  1028. }
  1029.  
  1030.  
  1031. //========================================================================================
  1032. // CLASS THandleStream
  1033. //========================================================================================
  1034. #undef Inherited
  1035. #define Inherited TStream
  1036.  
  1037. #pragma segment MAStreamCreate
  1038. MA_DEFINE_CLASS_M1(THandleStream,
  1039.                    Inherited);
  1040.  
  1041. //----------------------------------------------------------------------------------------
  1042. // THandleStream constructor
  1043. //----------------------------------------------------------------------------------------
  1044. #pragma segment MAStreamCreate
  1045.  
  1046. THandleStream::THandleStream()
  1047. {
  1048.     fGrowthSize = 1;
  1049.     fHandle = NULL;
  1050.     fPosition = 0;
  1051.     fSavedState = 0;
  1052.     fSize = 0;
  1053. }
  1054.  
  1055. //----------------------------------------------------------------------------------------
  1056. // THandleStream::IHandleStream: 
  1057. //----------------------------------------------------------------------------------------
  1058. #pragma segment MAStreamCreate
  1059.  
  1060. void THandleStream::IHandleStream(Handle itsHandle,
  1061.                                   long growth)
  1062. {
  1063.     IStream();
  1064.  
  1065.     fGrowthSize = growth;
  1066.     fPosition = 0;
  1067.     if (itsHandle)
  1068.     {
  1069.         if (IsAResource(itsHandle))
  1070.         {
  1071.             FailInfo fi;
  1072.             Try(fi)
  1073.             {
  1074.                 ::LoadResource(itsHandle);        // ensure it's loaded in memory
  1075.                 FailResError();
  1076.                 fi.Success();
  1077.             }
  1078.             else
  1079.             {
  1080.                 Free();
  1081.                 fi.ReSignal();
  1082.             }
  1083.         }
  1084.         fSize = ::GetHandleSize(itsHandle);
  1085.         fSavedState = ::HGetState(itsHandle);
  1086.         ::HNoPurge(itsHandle);                    // ensure it's not purgeable
  1087.         fHandle = itsHandle;
  1088.     }
  1089. }
  1090.  
  1091. //----------------------------------------------------------------------------------------
  1092. // THandleStream::Free: 
  1093. //----------------------------------------------------------------------------------------
  1094. #pragma segment MAStreamFree
  1095.  
  1096. THandleStream::~THandleStream()
  1097. {
  1098.     if (fHandle)
  1099.     {
  1100.         SetSize(GetPosition());                    // Trim the handle to its current position. 
  1101.         ::HSetState(fHandle, fSavedState);
  1102.     }
  1103. }
  1104.  
  1105. //----------------------------------------------------------------------------------------
  1106. // THandleStream::GetPosition: 
  1107. //----------------------------------------------------------------------------------------
  1108. #pragma segment MAStreamUtil
  1109.  
  1110. long THandleStream::GetPosition()                // override 
  1111. {
  1112.     return fPosition;
  1113. }
  1114.  
  1115. //----------------------------------------------------------------------------------------
  1116. // THandleStream::GetSize: 
  1117. //----------------------------------------------------------------------------------------
  1118. #pragma segment MAStreamUtil
  1119.  
  1120. long THandleStream::GetSize()                    // override 
  1121. {
  1122.     return fSize;
  1123. }
  1124.  
  1125. //----------------------------------------------------------------------------------------
  1126. // THandleStream::GrowthSize: 
  1127. //----------------------------------------------------------------------------------------
  1128. #pragma segment MAStreamUtil
  1129.  
  1130. long THandleStream::GrowthSize(long needed)
  1131. {
  1132.     return Max(fGrowthSize, needed);
  1133. }
  1134.  
  1135.  
  1136. //----------------------------------------------------------------------------------------
  1137. // THandleStream::SetPosition: 
  1138. //----------------------------------------------------------------------------------------
  1139. #pragma segment MAStreamUtil
  1140.  
  1141. void THandleStream::SetPosition(long newPosition)// override 
  1142. {
  1143.     OSErr err;
  1144.  
  1145.     if (newPosition < 0)                        // Same error returned by File Manager. 
  1146.         FailOSErr(posErr);
  1147.     else if (newPosition > fSize)                // Hit the end of the stream. 
  1148.     {
  1149.         newPosition = fSize;                    // We still want to position to end of the stream.
  1150.         err = eofErr;
  1151.     }
  1152.     else
  1153.         err = noErr;
  1154.  
  1155.     fPosition = newPosition;
  1156.     FailOSErr(err);
  1157. }
  1158.  
  1159. //----------------------------------------------------------------------------------------
  1160. // THandleStream::SetSize: 
  1161. //----------------------------------------------------------------------------------------
  1162. #pragma segment MAStreamUtil
  1163.  
  1164. void THandleStream::SetSize(long newSize)        // override 
  1165. {
  1166.     SetPermHandleSize(fHandle, newSize);
  1167.  
  1168.     if (newSize < fPosition)                    // If we shrunk the size, then adjust position and size
  1169.         fPosition = newSize;
  1170.  
  1171.     fSize = newSize;
  1172. }
  1173.  
  1174. //----------------------------------------------------------------------------------------
  1175. // THandleStream::ReadBytes: 
  1176. //----------------------------------------------------------------------------------------
  1177. #pragma segment MAStreamRead
  1178.  
  1179. void THandleStream::ReadBytes(void* p,
  1180.                               long count)        // override 
  1181. {
  1182.     OSErr err = noErr;
  1183.  
  1184.     register long available = fSize - fPosition;// Bytes available in the stream. 
  1185.  
  1186.     if (available < count)                        // About to read past end of stream. 
  1187.     {
  1188.         count = available;
  1189.         err = eofErr;
  1190.     }
  1191.  
  1192.     if (count > 0)                                // Move the bytes. 
  1193.     {
  1194.         MABlockMove(*fHandle + fPosition, p, count);
  1195.         fPosition += count;
  1196.     }
  1197.     else if (count < 0)
  1198.         err = paramErr;                            // Negative request count. 
  1199.  
  1200.     FailOSErr(err);
  1201. }
  1202.  
  1203. //----------------------------------------------------------------------------------------
  1204. // THandleStream::WriteBytes: 
  1205. //----------------------------------------------------------------------------------------
  1206. #pragma segment MAStreamWrite
  1207.  
  1208. void THandleStream::WriteBytes(const void* p,
  1209.                                long count)        // override 
  1210. {
  1211.     if (count < 0)
  1212.         FailOSErr(paramErr);                    // Negtive request count. 
  1213.  
  1214.     long available = fSize - fPosition;            // Bytes available in the stream. 
  1215.  
  1216.     if (available < count)                        // Grow the handle to accommodate request. 
  1217.     {
  1218.         // code as 2 statements to avoid interference of memory move in call to GrowthSize
  1219.         long itsGrowthSize = GrowthSize(count - available);
  1220.         SetSize(fSize + itsGrowthSize);
  1221.     }
  1222.  
  1223.     MABlockMove(p, *fHandle + fPosition, count);// Move the bytes. 
  1224.  
  1225.     fPosition += count;                            // Advance the position. 
  1226.  
  1227.     if (fPosition > fSize)                        // Adjust the size if necessary. 
  1228.         fSize = fPosition;
  1229. }
  1230.  
  1231.  
  1232. //========================================================================================
  1233. // CLASS TCountingStream
  1234. //========================================================================================
  1235. #undef Inherited
  1236. #define Inherited TStream
  1237.  
  1238. #pragma segment MAStreamCreate
  1239. MA_DEFINE_CLASS_M1(TCountingStream,
  1240.                    Inherited);
  1241.  
  1242. //----------------------------------------------------------------------------------------
  1243. // TCountingStream constructor
  1244. //----------------------------------------------------------------------------------------
  1245. #pragma segment MAStreamCreate
  1246.  
  1247. TCountingStream::TCountingStream()
  1248. {
  1249.     fPosition = 0;
  1250.     fSize = 0;
  1251. }
  1252.  
  1253. //----------------------------------------------------------------------------------------
  1254. // TCountingStream destructor
  1255. //----------------------------------------------------------------------------------------
  1256. #pragma segment MADestructorRes
  1257.  
  1258. TCountingStream::~TCountingStream()
  1259. {
  1260. }
  1261.  
  1262. //----------------------------------------------------------------------------------------
  1263. // TCountingStream::GetPosition: 
  1264. //----------------------------------------------------------------------------------------
  1265. #pragma segment MAStreamUtil
  1266.  
  1267. long TCountingStream::GetPosition()                // override 
  1268. {
  1269.     return fPosition;
  1270. }
  1271.  
  1272. //----------------------------------------------------------------------------------------
  1273. // TCountingStream::SetPosition: 
  1274. //----------------------------------------------------------------------------------------
  1275. #pragma segment MAStreamUtil
  1276.  
  1277. void TCountingStream::SetPosition(long newPosition)// Override
  1278. {
  1279.     OSErr err;
  1280.  
  1281.     if (newPosition < 0)                        // Same error returned by File Manager. 
  1282.         FailOSErr(posErr);
  1283.     else if (newPosition > fSize)                // Hit the end of the stream. 
  1284.     {
  1285.         newPosition = fSize;                    // We still want to position to end of the stream. 
  1286.         err = eofErr;
  1287.     }
  1288.     else
  1289.         err = noErr;
  1290.  
  1291.     fPosition = newPosition;
  1292.     FailOSErr(err);
  1293. }
  1294.  
  1295. //----------------------------------------------------------------------------------------
  1296. // TCountingStream::GetSize: 
  1297. //----------------------------------------------------------------------------------------
  1298. #pragma segment MAStreamUtil
  1299.  
  1300. long TCountingStream::GetSize()                    // override 
  1301. {
  1302.     return fSize;
  1303. }
  1304.  
  1305. //----------------------------------------------------------------------------------------
  1306. // TCountingStream::SetSize: 
  1307. //----------------------------------------------------------------------------------------
  1308. #pragma segment MAStreamUtil
  1309. void TCountingStream::SetSize(long newSize)        // Override
  1310. {
  1311.     if (newSize < fPosition)                    // If we shrunk the size, then we have to adjust the position. 
  1312.         fPosition = newSize;
  1313.     fSize = newSize;
  1314. }
  1315.  
  1316.  
  1317. //----------------------------------------------------------------------------------------
  1318. // TCountingStream::WriteBytes: 
  1319. //----------------------------------------------------------------------------------------
  1320. #pragma segment MAStreamWrite
  1321.  
  1322. void TCountingStream::WriteBytes(const void*    /* p */ ,
  1323.                                  long count)    // override 
  1324. {
  1325.     if (count < 0)                                // Can't write negative number of bytes. 
  1326.         FailOSErr(paramErr);
  1327.  
  1328.     fPosition += count;                            // Advance the position. 
  1329.  
  1330.     if (fPosition > fSize)                        // Adjust the size if necessary. 
  1331.         fSize = fPosition;
  1332. }
  1333.  
  1334.  
  1335.  
  1336. //========================================================================================
  1337. // CLASS TResourceStream
  1338. //========================================================================================
  1339. #undef Inherited
  1340. #define Inherited TStream
  1341.  
  1342. #pragma segment MAStreamCreate
  1343. MA_DEFINE_CLASS_M1(TResourceStream,
  1344.                    Inherited);
  1345.  
  1346. //----------------------------------------------------------------------------------------
  1347. // TResourceStream constructor
  1348. //----------------------------------------------------------------------------------------
  1349. #pragma segment MAStreamCreate
  1350.  
  1351. TResourceStream::TResourceStream()
  1352. {
  1353.     fResource = NULL;
  1354.     fPosition = 0;
  1355.     fSize = 0;
  1356. }
  1357.  
  1358. //----------------------------------------------------------------------------------------
  1359. // TResourceStream destructor
  1360. //----------------------------------------------------------------------------------------
  1361. #pragma segment MADestructorRes
  1362.  
  1363. TResourceStream::~TResourceStream()
  1364. {
  1365. }
  1366.  
  1367. //----------------------------------------------------------------------------------------
  1368. // TResourceStream::IResourceStream: 
  1369. //----------------------------------------------------------------------------------------
  1370. #pragma segment MAStreamCreate
  1371.  
  1372. void TResourceStream::IResourceStream(ResType theType,
  1373.                                       ResNumber theID)
  1374. {
  1375.     IStream();
  1376.  
  1377.     FailInfo fi;
  1378.     Try(fi)
  1379.     {
  1380.         short oldResLoad = LMGetResLoad();
  1381.         SetResLoad(FALSE);
  1382.         fResource = GetResource(theType, theID);
  1383.         SetResLoad(oldResLoad);
  1384.         FailNILResource(fResource);
  1385.  
  1386.         fSize = GetResourceSizeOnDisk(fResource);
  1387.         FailResError();
  1388.  
  1389.         fi.Success();
  1390.     }
  1391.     else
  1392.     {
  1393.         Free();
  1394.         fi.ReSignal();
  1395.     }
  1396. }
  1397.  
  1398. //----------------------------------------------------------------------------------------
  1399. // TResourceStream::GetPosition: 
  1400. //----------------------------------------------------------------------------------------
  1401. #pragma segment MAStreamUtil
  1402.  
  1403. long TResourceStream::GetPosition()                // override 
  1404. {
  1405.     return fPosition;
  1406. }
  1407.  
  1408. //----------------------------------------------------------------------------------------
  1409. // TResourceStream::SetPosition: 
  1410. //----------------------------------------------------------------------------------------
  1411. #pragma segment MAStreamUtil
  1412.  
  1413. void TResourceStream::SetPosition(long newPosition)// override 
  1414. {
  1415.     fPosition = newPosition;
  1416. }
  1417.  
  1418. //----------------------------------------------------------------------------------------
  1419. // TResourceStream::GetSize: 
  1420. //----------------------------------------------------------------------------------------
  1421. #pragma segment MAStreamUtil
  1422.  
  1423. long TResourceStream::GetSize()
  1424. {
  1425.     return fSize;
  1426. }
  1427.  
  1428. //----------------------------------------------------------------------------------------
  1429. // TResourceStream::SetSize: 
  1430. //----------------------------------------------------------------------------------------
  1431. #pragma segment MAStreamUtil
  1432.  
  1433. void TResourceStream::SetSize(long newSize)        // override 
  1434. {
  1435.     SetResourceSize(fResource, newSize);
  1436.     FailResError();
  1437.  
  1438.     fSize = newSize;                            // update if successfull
  1439.  
  1440.     if (newSize < fPosition)                    // If we shrunk the size, then we have to adjust the position.
  1441.         fPosition = newSize;
  1442. }
  1443.  
  1444. //----------------------------------------------------------------------------------------
  1445. // TResourceStream::WriteBytes: 
  1446. //----------------------------------------------------------------------------------------
  1447. #pragma segment MASectionWrite
  1448.  
  1449. void TResourceStream::WriteBytes(const void* p,
  1450.                                  long count)
  1451. {
  1452.     register long minSize = GetPosition() + count;
  1453.     if (minSize > GetSize())
  1454.         SetSize(minSize);                        // increase the size before writing
  1455.     WritePartialResource(fResource, GetPosition(), p, count);
  1456.     FailResError();
  1457.  
  1458.     SetPosition(minSize);                        // Advance the position. 
  1459. }
  1460.  
  1461. //----------------------------------------------------------------------------------------
  1462. // TResourceStream::ReadBytes: 
  1463. //----------------------------------------------------------------------------------------
  1464. #pragma segment MAStreamRead
  1465.  
  1466. void TResourceStream::ReadBytes(void* p,
  1467.                                 long count)        // override 
  1468. {
  1469.     register long minToRead = Min(count, GetSize() - GetPosition());
  1470.     ReadPartialResource(fResource, GetPosition(), p, minToRead);
  1471.     FailResError();
  1472.  
  1473.     SetPosition(GetPosition() + minToRead);        // Advance the position. 
  1474. }
  1475.  
  1476. //----------------------------------------------------------------------------------------
  1477. // End of UStream.cp
  1478.  
  1479. #pragma segment Inline
  1480.  
  1481.